﻿using System;
using System.IO;
using System.Text;
using System.Web;
using System.Configuration;
using JSC.Core;
using JSC.Core.Helper;
using JSC.Portal.Web.Helper;

namespace JSC.Portal.Web.Handlers.Asset
{
    /// <summary>
    /// Original code copied from KiGG
    /// </summary>
    public class AssetHandler : BaseHandler
    {
        public AssetHandler()
        {
            Settings = (AssetSettingsSection)ConfigurationManager.GetSection(AssetSettingsSection.SectionName);
        }

        public AssetSettingsSection Settings
        {
            get;
            private set;
        }

        public override void ProcessRequest(HttpContextBase context)
        {
            string assetName = context.Request.QueryString["name"];

            if (!string.IsNullOrEmpty(assetName))
            {
                AssetElement setting = GetSetting(Settings, assetName);

                if (setting != null)
                {
                    HandlerCacheItem asset = GetAsset(context, setting);

                    if (asset != null)
                    {
                        if (setting.GenerateETag)
                        {
                            if (HandleIfNotModified(context, asset.ETag))
                            {
                                return;
                            }
                        }

                        HttpResponseBase response = context.Response;

                        // Set the content type
                        response.ContentType = setting.ContentType;

                        // Compress
                        if (setting.Compress)
                        {
                            context.CompressResponse();
                        }

                        // Write
                        using (StreamWriter sw = new StreamWriter(response.OutputStream))
                        {
                            sw.Write(asset.Content);
                        }

                        // Cache
                        if (setting.CacheDurationInDays > 0)
                        {
                            // Helpful when hosting in Single Web server
                            if (setting.GenerateETag)
                            {
                                response.Cache.SetETag(asset.ETag);
                            }

                            context.CacheResponseFor(TimeSpan.FromDays(setting.CacheDurationInDays));
                        }
                    }
                }
            }
        }

        private static AssetElement GetSetting(AssetSettingsSection settings, string assetName)
        {
            AssetElement setting = settings.Assets[assetName];
            AssetElement clone = null;

            if (setting != null)
            {
                clone = new AssetElement
                {
                    Name = setting.Name,
                    ContentType = setting.ContentType,
                    Compress = setting.Compress,
                    GenerateETag = setting.GenerateETag,
                    Version = setting.Version,
                    CacheDurationInDays = setting.CacheDurationInDays,
                    Directory = setting.Directory,
                    Files = setting.Files
                };

                // Assign Global value if Value is default
                if ((clone.Compress == AssetSettingsSection.DefaultCompress) && (settings.Compress != AssetSettingsSection.DefaultCompress))
                {
                    clone.Compress = settings.Compress;
                }

                // Assign Global value if Value is default
                if ((clone.GenerateETag == AssetSettingsSection.DefaultGenerateETag) && (settings.GenerateETag != AssetSettingsSection.DefaultGenerateETag))
                {
                    clone.GenerateETag = settings.GenerateETag;
                }

                // Assign Global value if Value is default
                if ((clone.CacheDurationInDays == AssetSettingsSection.DefaultCacheDurationInDays) && (settings.CacheDurationInDays != AssetSettingsSection.DefaultCacheDurationInDays))
                {
                    clone.CacheDurationInDays = settings.CacheDurationInDays;
                }

                // Assign the global version if setting does not have any version
                if (string.IsNullOrEmpty(clone.Version))
                {
                    clone.Version = settings.Version;
                }
            }

            return clone;
        }

        private HandlerCacheItem GetAsset(HttpContextBase context, AssetElement setting)
        {
            string key = "cache:{0}".FormatWith(setting.Name);
            HandlerCacheItem asset = context.Cache.Get(key) as HandlerCacheItem;

            if (asset == null)
            {
                string[] files = setting.Files.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                if (files.Length > 0)
                {
                    StringBuilder contentBuilder = new StringBuilder();

                    for (int i = 0; i < files.Length; i++)
                    {
                        string file = context.Server.MapPath(Path.Combine(setting.Directory, files[i]));
                        string fileContent = File.ReadAllText(file);

                        if (!string.IsNullOrEmpty(fileContent))
                        {
                            contentBuilder.AppendLine(fileContent);
                            contentBuilder.AppendLine();
                        }
                    }

                    string content = contentBuilder.ToString();

                    if (!string.IsNullOrEmpty(content))
                    {
                        asset = new HandlerCacheItem { Content = content };

                        bool contains = context.Cache[key] != null;
                        if ((setting.CacheDurationInDays > 0) && (context.Cache[key] == null))
                        {
                            context.Cache.Insert(key, asset, null, DateTime.Now.AddDays(setting.CacheDurationInDays), System.Web.Caching.Cache.NoSlidingExpiration);
                        }
                    }
                }
            }

            return asset;
        }
    }
}
